<template>
  <div class="workflow-editor">
    <!-- 左侧工具栏 -->
    <div class="tools-panel">
      <workflow-toolbar 
        @save="saveWorkflow"
        @import="importWorkflow"
        @export="exportWorkflow"
      />
    </div>

    <!-- 右侧画布 -->
    <div class="canvas-panel">
      <workflow-canvas 
        ref="canvas"
        :workflow-data="workflowData"
        @node-context-menu="handleNodeContextMenu"
        @edge-context-menu="handleEdgeContextMenu"
        @node-selected="handleNodeSelected"
        @blank-click="handleCanvasBlankClick"
        @node-click="handleNodeClick"
        @edge-click="handleEdgeClick"
      />
    </div>

    <!-- 节点配置抽屉 -->
    <component
      v-if="currentDrawerComponent && drawerVisible"
      :is="currentDrawerComponent"
      :visible="drawerVisible"
      :node-data="currentNode"
      :edge-data="currentEdge"
      @save="handleDrawerSave"
      @close="handleDrawerClose"
    />

    <!-- 右键菜单 -->
    <node-context-menu 
      :visible="contextMenuVisible" 
      :x="contextMenuPosition.x"
      :y="contextMenuPosition.y"
      :node-type="currentNode?.data?.type"
      :undeletable="currentNode?.data?.undeletable === true"
      @change-node="changeNode"
      @copy="copyNode"
      @duplicate="duplicateNode"
      @delete="deleteSelected"
      @open-help="openHelp"
      @open-about="openAbout"
      @define-reply="defineReply"
      @author-info="showAuthor"
    />

    <edge-context-menu 
      :visible="edgeMenuVisible" 
      :x="contextMenuPosition.x"
      :y="contextMenuPosition.y"
      @change-edge="changeEdge"
      @copy="copyEdge"
      @duplicate="duplicateEdge"
      @delete="deleteSelected"
      @open-help="openHelp"
      @open-about="openAbout"
      @define-reply="defineReply"
      @author-info="showAuthor"
    />
  </div>
</template>

<script>
import { defineComponent, ref, computed, onMounted, provide } from 'vue'
import { ElMessage } from 'element-plus'
import { componentRegistry } from '@/components/WorkFlow/core/ComponentRegistry'
import '@/components/WorkFlow/core/ComponentRegistrations' // 导入组件注册配置
import WorkflowToolbar from '@/components/WorkFlow/editor/WorkflowToolbar.vue'
import WorkflowCanvas from '@/components/WorkFlow/editor/WorkflowCanvas.vue'
import NodeContextMenu from '@/components/WorkFlow/menu/NodeContextMenu.vue'
import EdgeContextMenu from '@/components/WorkFlow/menu/EdgeContextMenu.vue'
import { workflowApi } from '@/api/workflow'

/**
 * 工作流编辑器主组件
 * 提供可视化的工作流编辑功能，支持多种节点类型和配置
 */
export default defineComponent({
  name: 'WorkflowEditor',
  
  components: {
    WorkflowToolbar,
    WorkflowCanvas,
    NodeContextMenu,
    EdgeContextMenu
  },

  props: {
    workflowId: {
      type: String,
      default: ''
    }
  },

  setup(props) {
    const canvas = ref(null)
    const workflowData = ref({})
    const currentNode = ref(null)
    const currentEdge = ref(null)
    const drawerVisible = ref(false)
    const contextMenuVisible = ref(false)
    const edgeMenuVisible = ref(false)
    const contextMenuPosition = ref({ x: 0, y: 0 })
    const drawerDataTick = ref(0)

    // 计算属性
    const nodeTypes = computed(() => componentRegistry.getNodeTypes())
    
    const currentDrawerComponent = computed(() => {
      if (currentNode.value) {
        return componentRegistry.getDrawerComponent(currentNode.value.data?.type)
      }
      if (currentEdge.value) {
        return componentRegistry.getDrawerComponent('transition')
      }
      return null
    })

    // 提供全局方法给子组件
    provide('workflowEditor', {
      getGraph: () => canvas.value?.getGraph(),
      getWorkflowData: () => workflowData.value,
      updateWorkflowData: (data) => {
        workflowData.value = { ...workflowData.value, ...data }
      }
    })

    // 生命周期
    onMounted(async () => {
      if (props.workflowId) {
        await loadWorkflow(props.workflowId)
      }
    })

    // 方法
    const loadWorkflow = async (id) => {
      try {
        const response = await workflowApi.getWorkflowDetail(id)
        workflowData.value = response.data
        if (canvas.value) {
          canvas.value.loadData(workflowData.value)
        }
      } catch (error) {
        ElMessage.error('加载工作流失败')
        console.error('加载工作流失败:', error)
      }
    }

    const saveWorkflow = async () => {
      try {
        if (!canvas.value) return
        
        const data = canvas.value.exportData()
        const saveData = {
          ...workflowData.value,
          ...data,
          id: props.workflowId
        }

        if (props.workflowId) {
          await workflowApi.updateWorkflow(saveData)
        } else {
          await workflowApi.createWorkflow(saveData)
        }
        
        ElMessage.success('保存成功')
      } catch (error) {
        ElMessage.error('保存失败')
        console.error('保存失败:', error)
      }
    }



    const handleNodeContextMenu = (node, position) => {
      currentNode.value = node
      currentEdge.value = null
      contextMenuPosition.value = position
      contextMenuVisible.value = true
    }

    const handleEdgeContextMenu = (edge, position) => {
      currentEdge.value = edge
      currentNode.value = null
      contextMenuPosition.value = position
      edgeMenuVisible.value = true
    }

    const handleNodeClick = (node) => {
      currentNode.value = node
      currentEdge.value = null
      openDrawer()
    }

    /**
     * 选中节点时打开配置抽屉
     * @param {Object} node - 选中的节点
     */
    const handleNodeSelected = (node) => {
      currentNode.value = node
      currentEdge.value = null
      openDrawer()
    }

    const handleEdgeClick = (edge) => {
      currentEdge.value = edge
      currentNode.value = null
      openDrawer()
    }

    /**
     * 打开抽屉并关闭所有右键菜单
     */
    const openDrawer = () => {
      drawerVisible.value = true
      contextMenuVisible.value = false
      edgeMenuVisible.value = false
    }

    const handleDrawerSave = (data) => {
      if (currentNode.value) {
        canvas.value?.updateNodeData(currentNode.value, data)
      } else if (currentEdge.value) {
        canvas.value?.updateEdgeData(currentEdge.value, data)
      }
    }

    const handleDrawerClose = () => {
      drawerVisible.value = false
      drawerDataTick.value++
    }

    /**
     * 删除选中元素（跳过不可删除节点）
     */
    const deleteSelected = () => {
      const g = canvas.value?.getGraph()
      if (!g) return
      const selected = g.getSelectedCells()
      if (!selected || selected.length === 0) {
        // 兼容右键菜单针对当前选中引用的删除
        if (currentNode.value) {
          const d = currentNode.value.getData() || {}
          if (d.undeletable === true || d.type === 'start' || d.type === 'end') {
            ElMessage.warning('该节点不可删除')
          } else {
            canvas.value?.deleteNode(currentNode.value)
          }
        } else if (currentEdge.value) {
          canvas.value?.deleteEdge(currentEdge.value)
        }
      } else {
        selected.forEach(cell => {
          try {
            if (cell.isNode && cell.isNode()) {
              const d = cell.getData() || {}
              if (d.undeletable === true || d.type === 'start' || d.type === 'end') return
              g.removeNode(cell)
            } else if (cell.isEdge && cell.isEdge()) {
              g.removeEdge(cell)
            }
          } catch (e) {}
        })
      }
      contextMenuVisible.value = false
      edgeMenuVisible.value = false
    }

    /**
     * 画布空白点击时关闭所有右键菜单
     */
    const handleCanvasBlankClick = () => {
      contextMenuVisible.value = false
      edgeMenuVisible.value = false
    }

    /**
     * 更改节点（打开节点配置抽屉）
     */
    const changeNode = () => {
      openDrawer()
    }

    /**
     * 更改边（打开边配置抽屉）
     */
    const changeEdge = () => {
      openDrawer()
    }

    /**
     * 拷贝节点为 JSON 到剪贴板
     */
    const copyNode = async () => {
      try {
        if (!currentNode.value) return
        const t = currentNode.value.getData()?.type
        if (t === 'start' || t === 'end') {
          ElMessage.warning('该节点不可拷贝')
          contextMenuVisible.value = false
          return
        }
        const json = currentNode.value.toJSON ? currentNode.value.toJSON() : currentNode.value.data
        await navigator.clipboard.writeText(JSON.stringify(json, null, 2))
        ElMessage.success('已拷贝节点数据到剪贴板')
        contextMenuVisible.value = false
      } catch (e) {
        ElMessage.error('拷贝失败')
      }
    }

    /**
     * 拷贝边为 JSON 到剪贴板
     */
    const copyEdge = async () => {
      try {
        if (!currentEdge.value) return
        const json = currentEdge.value.toJSON ? currentEdge.value.toJSON() : currentEdge.value.data
        await navigator.clipboard.writeText(JSON.stringify(json, null, 2))
        ElMessage.success('已拷贝边数据到剪贴板')
        edgeMenuVisible.value = false
      } catch (e) {
        ElMessage.error('拷贝失败')
      }
    }

    /**
     * 复制节点（在画布中创建一个偏移的新副本）
     */
    const duplicateNode = () => {
      try {
        const g = canvas.value?.getGraph()
        const n = currentNode.value
        if (!g || !n) return
        const t = n.getData()?.type
        if (t === 'start' || t === 'end') {
          ElMessage.warning('该节点不可复制')
          contextMenuVisible.value = false
          return
        }
        const meta = n.toJSON ? n.toJSON() : null
        if (!meta) return
        delete meta.id
        // 复制的节点不继承不可删除标记
        if (meta.data && meta.data.undeletable === true) {
          meta.data.undeletable = false
        }
        if (meta.position) {
          meta.position.x = (meta.position.x || 0) + 30
          meta.position.y = (meta.position.y || 0) + 30
        }
        g.addNode(meta)
        ElMessage.success('已复制一个节点')
        contextMenuVisible.value = false
      } catch (e) {
        ElMessage.error('复制失败')
      }
    }

    /**
     * 复制边（在画布中创建一个新的同源同目标的边）
     */
    const duplicateEdge = () => {
      try {
        const g = canvas.value?.getGraph()
        const e = currentEdge.value
        if (!g || !e) return
        const meta = e.toJSON ? e.toJSON() : null
        if (!meta) return
        delete meta.id
        // 保持相同端点即可，允许多边
        g.addEdge(meta)
        ElMessage.success('已复制一条边')
        edgeMenuVisible.value = false
      } catch (err) {
        ElMessage.error('复制失败')
      }
    }

    /**
     * 打开帮助文档（占位）
     */
    const openHelp = () => {
      ElMessage.info('暂未配置帮助文档')
      contextMenuVisible.value = false
    }

    /**
     * 关于信息（占位）
     */
    const openAbout = () => {
      ElMessage.info('RuoYi-Vue3 工作流编辑器')
      contextMenuVisible.value = false
    }

    /**
     * 定义一个聊天对话的回复内容（占位）
     */
    const defineReply = () => {
      ElMessage.info('请在节点配置中定义回复内容')
      contextMenuVisible.value = false
    }

    /**
     * 显示作者信息（占位）
     */
    const showAuthor = () => {
      ElMessage.info('作者 Dify')
      contextMenuVisible.value = false
    }

    const importWorkflow = async (file) => {
      try {
        const data = await readFileAsJson(file)
        workflowData.value = data
        if (canvas.value) {
          canvas.value.loadData(data)
        }
        ElMessage.success('导入成功')
      } catch (error) {
        ElMessage.error('导入失败')
        console.error('导入失败:', error)
      }
    }

    const exportWorkflow = () => {
      if (!canvas.value) return
      
      const data = canvas.value.exportData()
      const blob = new Blob([JSON.stringify(data, null, 2)], {
        type: 'application/json'
      })
      
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = `workflow_${Date.now()}.json`
      link.click()
      URL.revokeObjectURL(url)
    }

    const readFileAsJson = (file) => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = (e) => {
          try {
            resolve(JSON.parse(e.target.result))
          } catch (error) {
            reject(new Error('文件格式错误'))
          }
        }
        reader.onerror = () => reject(new Error('读取文件失败'))
        reader.readAsText(file)
      })
    }

    return {
      canvas,
      workflowData,
      currentNode,
      currentEdge,
      drawerVisible,
      contextMenuVisible,
      edgeMenuVisible,
      contextMenuPosition,
      nodeTypes,
      currentDrawerComponent,
      saveWorkflow,
      handleNodeContextMenu,
      handleEdgeContextMenu,
      handleNodeClick,
      handleNodeSelected,
      handleEdgeClick,
      handleDrawerSave,
      handleDrawerClose,
      deleteSelected,
      handleCanvasBlankClick,
      changeNode,
      changeEdge,
      copyNode,
      copyEdge,
      duplicateNode,
      duplicateEdge,
      openHelp,
      openAbout,
      defineReply,
      showAuthor,
      importWorkflow,
      exportWorkflow
    }
  }
})
</script>

<style scoped>
.workflow-editor {
  display: flex;
  height: 100vh;
  background: #f5f5f5;
}

.tools-panel {
  width: 200px;
  background: #fff;
  border-right: 1px solid #e8e8e8;
  overflow-y: auto;
}

.canvas-panel {
  flex: 1;
  position: relative;
  background: #fff;
}
</style>
